import selectors
import socket
import logging
import datetime

FORMAT = "%(asctime)s %(processName)s %(process)s %(threadName)s %(thread)s %(message)s"
logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt='%Y%m%d-%H:%M:%S')


class ChatServer:
    def __init__(self,ip='127.0.0.1',port=9999,client={}):
        self.server = socket.socket()
        self.addr = ip,port
        self.selector = selectors.DefaultSelector()
        self.__clients = client


    def start(self):
        self.server.bind(self.addr)
        self.server.listen()
        self.key = self.selector.register(self.server, selectors.EVENT_READ, self.__accept)
        logging.info(self.key)

        while True:
            events = self.selector.select()
            # print(len(events), '+++++++')
            for key, mask in events:
                # logging.info(key)
                key.data(key.fileobj, mask)

    def __accept(self,sock:socket.socket,mask):
        conn,raddr = sock.accept()
        self.__clients[raddr] = conn
        # print(self.__clients.items())
        conn.setblocking(False)
        # logging.info(conn)
        # logging.info(raddr)

        newkey = self.selector.register(conn, selectors.EVENT_READ, self.__recv)
        logging.info(newkey)

    def __recv(self,clientsock:socket.socket,mask):
        try:
            data = clientsock.recv(1024)
            if not data or data.strip() == b'quit':
                self.selector.unregister(clientsock)
                self.__clients.pop(clientsock.getpeername())
                clientsock.close()
                return
            msg = '{} From {}:{} msg={}'.format(datetime.datetime.now().strftime('%Y%m%d-%H:%M:%S'),*clientsock.getsockname(), data.decode()).encode()
            logging.info(msg)
            for c in self.__clients.values():
                c.send(msg)
            # clientsock.send()
        except Exception as e:
            self.selector.unregister(clientsock)
            clientsock.close()
            logging.error(e)

    # def stop(self):
    #     self.selector.unregister(self.server)
    #     self.server.close()

cs = ChatServer()
cs.start()
